package 代码题.生产者消费者题目;

import java.util.LinkedList;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * 使用 lock锁+自定义的阻塞队列 实现生产者消费者模式
 * 大家都是在队列里面锁住数据，而不是在线程刚出现的时候
 */
public class LockStrategy {
    public static void main(String[] args) {
        SelfQueue selfqueue = new SelfQueue();
        Thread prodThread = new Thread(new LockProducer(selfqueue));
        Thread consThread = new Thread(new LockConsumer(selfqueue));
        prodThread.start();
        consThread.start();
    }
}

/**
 * 自定义的队列，实现加锁的put和get
 * 使用一个lock和附加的两个condition
 */
class SelfQueue {
    int max = 5;
    LinkedList<Integer> ProdLine = new LinkedList<Integer>();
    Lock lock = new ReentrantLock();
    Condition full = lock.newCondition();   //只有两种状态，类似于true和false
    Condition empty = lock.newCondition();

    public void produce(int ProdRandom) {
        try {
            lock.lock();
            while (max == ProdLine.size()) {
                System.out.println("存储量达到上限，请等待");
                full.await();   //挂牵当前线程，释放lock的锁
            }
            ProdLine.add(ProdRandom);
            empty.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

    public int consume() {
        int m = 0;
        try {
            lock.lock();
            while (ProdLine.size() == 0) {
                System.out.println("队列是空的，请稍候");
                empty.await();  //挂起当前线程，释放lock锁
            }
            m = ProdLine.removeFirst();
            full.signal();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
            return m;
        }
    }
}

//生产者
class LockProducer implements Runnable {
    private final SelfQueue selfqueue;
    public LockProducer(SelfQueue selfqueue) {
        this.selfqueue = selfqueue;
    }
    public void run() {
        for (int i = 0; i < 10; i++) {
            System.out.println("生产的数据: " + i);
            selfqueue.produce(i);
        }
    }
}

//消费者
class LockConsumer implements Runnable {
    private final SelfQueue selfqueue;
    public LockConsumer(SelfQueue selfqueue) {
        this.selfqueue = selfqueue;
    }
    public void run() {
        while (true) {
            System.out.println("消费的数据: " + selfqueue.consume());
        }
    }
}
